package com.sinodata.bsm.inmp.task.gab;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.TableEvent;

import com.sinodata.bsm.inmp.util.SnmpUtil;

/**
 * <p>
 * Description: 这个任务负责采集温湿度的性能数据，并将其放入performaceDataFromYC中。
 *              具体采集方法是：用snmp将当前性能数据一次性收集回来，收集到的数据总条数分别和ycp表中的总条数一致。
 *              用数据在snmp中出现的先后顺序为Key(从1开始),用数据值为value，将其一条一条放入performaceDataFromYC中。
 *              
 *              performaceDataFromYX和performaceDataFromYC使用相同的方法，只是访问的表是ycp。
 * </p>
 *
 * @author wangpeng
 * @version 1.0
 *
 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2013-9-5 上午10:57:12          wangpeng        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class WsdPerformaceDataCollectorJob implements Job {

    private static final Logger logger = Logger.getLogger(WsdPerformaceDataCollectorJob.class);
    private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static Long lastModified = null;
    private static Properties prop = null;
    /**
     * ycPerformaceDataPool和yxPerformaceDataPool为温湿度性能数据的一个数据池
     */
    private static final Map<Integer, Integer> ycPerformaceDataPool = new HashMap<Integer, Integer>();
    private static final Map<Integer, Integer> yxPerformaceDataPool = new HashMap<Integer, Integer>();

    public static Integer getYCValueByIndex(Integer index) {
        return ycPerformaceDataPool.get(index);
    }

    public static Integer getYXValueByIndex(Integer index) {
        return yxPerformaceDataPool.get(index);
    }

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        try {
            Vector<? extends VariableBinding> ycpVector = getYcpData();
            List<TableEvent> yxpList = getYxpData();
            rebuildDataPool(ycpVector, yxpList);
        } catch (IOException e) {
            logger.error(format.format(new Date()) + " wenshidu>>>> performance >>> getYcpData or getYxpData occured error", e);
        }
    }

    private Vector<? extends VariableBinding> getYcpData() throws IOException {
        Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
        snmp.listen();

        Properties properties = getProperties();
        OID oid = new OID(properties.getProperty("oid.ycp", "1.3.6.1.4.1.15.0.2"));
        int maxRepetitions = Integer.valueOf(properties.getProperty("rows.ycp", "678"));

        PDU pdu = SnmpUtil.createGetBulkPdu(oid, maxRepetitions);
        
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(properties.getProperty("community", "public")));
        target.setVersion(Integer.valueOf(properties.getProperty("version", "1")));
        target.setAddress(new UdpAddress(properties.getProperty("ip", "10.1.0.177") + "/" + properties.getProperty("prot", "161")));
        target.setTimeout(Long.valueOf(properties.getProperty("timeout", "60000")));
        target.setRetries(Integer.valueOf(properties.getProperty("retries", "0")));
        
        Vector<? extends VariableBinding> vector = SnmpUtil.sendRequest(snmp, pdu, target);
        return vector;
    }

    private List<TableEvent> getYxpData() throws IOException {
        Properties properties = getProperties();

        Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
        snmp.listen();

        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(properties.getProperty("community", "public")));
        target.setVersion(Integer.valueOf(properties.getProperty("version", "1")));
        target.setAddress(new UdpAddress(properties.getProperty("ip", "10.1.0.177") + "/" + properties.getProperty("prot", "161")));
        target.setTimeout(Long.valueOf(properties.getProperty("timeout", "60000")));
        target.setRetries(Integer.valueOf(properties.getProperty("retries", "0")));

        OID yxpOid = new OID(properties.getProperty("oid.yxp", "1.3.6.1.4.1.15.0.3"));
        OID[] columnOIDs = new OID[] { yxpOid };
        OID lowerBoundIndex = new OID(properties.getProperty("upsStartRowNo", "484"));
        OID upperBoundIndex = new OID(properties.getProperty("upsEndRowNo", "1218"));
        List<TableEvent> eventList = SnmpUtil.snmpWalk(snmp, target, columnOIDs, lowerBoundIndex, upperBoundIndex);
        return eventList;
    }

    private synchronized void rebuildDataPool(Vector<? extends VariableBinding> ycpVector, List<TableEvent> yxpList) {
        ycPerformaceDataPool.clear();
        if (ycpVector != null && ycpVector.size() > 0) {
            for (int i = 0; i < ycpVector.size(); i++) {
                Integer key = i + 1;
                Integer value = null;
                try {
                    value = ycpVector.get(i).getVariable().toInt();
                } catch (Exception e) {
                    value = -1;
                }
                ycPerformaceDataPool.put(key, value);
            }
        }
        logger.error(format.format(new Date()) + " wenshidu>>>> performance >>> ycPerformaceDataPool build finished");
        yxPerformaceDataPool.clear();
        if (yxpList != null && yxpList.size() > 0) {
            for (int i = 0; i < yxpList.size(); i++) {
                TableEvent event = yxpList.get(i);
                Integer key = Integer.valueOf(event.getIndex().toString().split("\\.")[0]);
                Integer value = null;
                try {
                    value = event.getColumns()[0].getVariable().toInt();
                } catch (Exception e) {
                    value = -1;
                }
                yxPerformaceDataPool.put(key, value);
            }
        }
        logger.error(format.format(new Date()) + " wenshidu>>>> performance >>> ycPerformaceDataPool build finished");
    }

    private Properties getProperties() {
        File file = new File("inmp-conf/gab-wsd.properties");
        if (prop == null) {
            prop = new Properties();
            InputStreamReader isr;
            try {
                lastModified = file.lastModified();
                isr = new InputStreamReader(new FileInputStream(file), "GBK");
                prop.load(isr);
                isr.close();
            } catch (Exception e) {
                logger.error("wsd>>>>  read file inmp-conf/gab-wsd.properties occured error", e);
            }
        } else if (!Long.valueOf(file.lastModified()).equals(lastModified)) {
            prop = new Properties();
            InputStreamReader isr;
            try {
                lastModified = file.lastModified();
                isr = new InputStreamReader(new FileInputStream(file), "GBK");
                prop.load(isr);
                isr.close();
            } catch (Exception e) {
                logger.error("wsd>>>>  read file inmp-conf/gab-wsd.properties occured error", e);
            }
        }
        return prop;
    }

    public static void main(String[] args) throws Exception {
    	WsdPerformaceDataCollectorJob job = new WsdPerformaceDataCollectorJob();
    	List<TableEvent> ycpVector = job.getYxpData();
    	System.out.println(ycpVector.size());
    }
}
